#include "OpenGLTexture.h"
#include "hzpch.h"

#include "stb_image.h"

namespace Hazel
{
OpenGLTexture2D::OpenGLTexture2D(const std::string &filepath) : m_Path(filepath)
{
    HZ_PROFILE_FUNC();

    int width, height, channels;
    stbi_set_flip_vertically_on_load(1);
    stbi_uc *data;
    {
        HZ_PROFILE_SCROPE("stbi_load - OpenGLTexture2D::OpenGLTexture2D(const std::string &filepath)");
        data = stbi_load(filepath.c_str(), &width, &height, &channels, 0);
    }
    HZ_CORE_ASSERT(data, "Failed to load image!");
    m_Width = width;
    m_Height = height;

    GLenum internalFormat = 0, dataFormat = 0;
    if (channels == 4)
    {
        internalFormat = GL_RGBA8;
        dataFormat = GL_RGBA;
    }
    else if (channels == 3)
    {
        internalFormat = GL_RGB8;
        dataFormat = GL_RGB;
    }

    m_InterFormate = internalFormat;
    m_DataFormat = dataFormat;

    HZ_CORE_ASSERT(internalFormat && dataFormat, "Format not supported!");

    glCreateTextures(GL_TEXTURE_2D, 1, &m_RendererID);
    glTextureStorage2D(m_RendererID, 1, internalFormat, m_Width, m_Height);

    glTextureParameteri(m_RendererID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);

    glTextureSubImage2D(m_RendererID, 0, 0, 0, m_Width, m_Height, dataFormat, GL_UNSIGNED_BYTE, data);

    stbi_image_free(data);
}
OpenGLTexture2D::OpenGLTexture2D(uint32_t width, uint32_t height) : m_Width(width), m_Height(height)
{
    HZ_PROFILE_FUNC();

    GLenum internalFormat = GL_RGBA8, dataFormat = GL_RGBA;

    m_InterFormate = internalFormat;
    m_DataFormat = dataFormat;

    HZ_CORE_ASSERT(internalFormat && dataFormat, "Format not supported!");

    glCreateTextures(GL_TEXTURE_2D, 1, &m_RendererID);
    glTextureStorage2D(m_RendererID, 1, internalFormat, m_Width, m_Height);

    glTextureParameteri(m_RendererID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
OpenGLTexture2D::~OpenGLTexture2D()
{
    HZ_PROFILE_FUNC();

    glDeleteTextures(1, &m_RendererID);
}
void OpenGLTexture2D::SetData(void *data, uint32_t size)
{
    HZ_PROFILE_FUNC();

    uint32_t bpp = m_DataFormat == GL_RGBA ? 4 : 3;
    HZ_CORE_ASSERT(size == m_Width * m_Height * bpp, "data must be entire texture!");
    glTextureSubImage2D(m_RendererID, 0, 0, 0, m_Width, m_Height, m_DataFormat, GL_UNSIGNED_BYTE, data);
}
void OpenGLTexture2D::Bind(uint32_t slot) const
{
    HZ_PROFILE_FUNC();

    glBindTextureUnit(slot, m_RendererID);
}
bool OpenGLTexture2D::operator==(const Texture &other) const
{
    return m_RendererID == ((OpenGLTexture2D &)other).m_RendererID;
}
} // namespace Hazel